package service;

import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.UUID;

import util.VerificadorExcecoes;

import model.Entrada;
import model.Grupo;
import model.Usuario;
import excecao.SistemaException;

public class GerenciadorGrupos {

	private HashMap<String, Grupo> mapeadorGrupos;

	public GerenciadorGrupos() {

		mapeadorGrupos = new HashMap<String, Grupo>();

	}

	/**
	 * 
	 * 
	 * @param emailUsuario
	 * @param nomeGrupo
	 * @param permissao
	 * @return
	 * @throws SistemaException
	 */
	public String criarGrupo(String emailUsuario, String nomeGrupo,
			String permissao) throws SistemaException {

		String idGrupo = UUID.randomUUID().toString();
		Grupo grupo = new Grupo(emailUsuario, nomeGrupo, permissao);
		mapeadorGrupos.put(idGrupo, grupo);
		return idGrupo;
	}

	/**
	 * 
	 * @param idGrupo
	 * @param atributo
	 * @return
	 * @throws SistemaException
	 */
	public String getAtributoGrupo(String idGrupo, String atributo)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		return grupo.getAtributo(atributo);

	}

	/**
	 * Verifica se existe um grupo com a id passada como parametro.
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo.
	 * @return True caso grupo existe, False caso contrario.
	 */
	private boolean validaGrupo(String idGrupo) {

		return mapeadorGrupos.containsKey(idGrupo);

	}

	/**
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo.
	 * @return Grupo identificado pela id passada como parametro.
	 * @throws SistemaException
	 */
	private Grupo getGrupo(String idGrupo) throws SistemaException {
		VerificadorExcecoes.verificaStringVazia(idGrupo,
				"Identificacao do grupo nao pode ser nula.");
		if (validaGrupo(idGrupo)) {
			return mapeadorGrupos.get(idGrupo);
		}
		throw new SistemaException("Grupo nao existe.");
	}

	/**
	 * Retorna o email do dono(criador) do grupo.
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo.
	 * @return email do dono do grupo.
	 * @throws SistemaException
	 */
	public String getDonoGrupo(String idGrupo) throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		return grupo.getDonoGrupo();

	}

	/**
	 * 
	 * @param idGrupo
	 * @return
	 * @throws SistemaException
	 */
	public String getMembrosGrupo(String idGrupo) throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		return grupo.getMembros();
	}

	/**
	 * Altera um atributo de um grupo
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo
	 * @param atributo
	 *            Atributo que se deseja alterar
	 * @param valor
	 *            Novo valor do atributo
	 * @throws SistemaException
	 *             Parametros invalidos.
	 */
	public void alteraGrupo(String idGrupo, String atributo, String valor)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		grupo.alteraAtributo(atributo, valor);

	}

	/**
	 * Adiciona entrada a um grupo
	 * 
	 * @param idGrupo
	 *            identificacao do grupo
	 * @param entrada
	 *            identificacao da entrada
	 * @throws SistemaException
	 */
	public void addEntrada(String idGrupo, Entrada entrada)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		grupo.addEntrada(entrada);

	}

	/**
	 * Retorna uma String contendo todas as Ids das entradas do grupo. A String
	 * segue o formato [valorId1, valorId2, valorId3]
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo
	 * @return String com ids de todas as entradas do grupo.
	 * @throws SistemaException
	 */
	public String getEntradasGrupo(String idGrupo) throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		return grupo.getEntradas();

	}

	/**
	 * 
	 * 
	 * @param idGrupo
	 * @param idEntrada
	 * @param atributo
	 * @return
	 * @throws SistemaException
	 */
	public String getAtributoEntradaGrupo(String idGrupo, String idEntrada,
			String atributo) throws SistemaException {
		Grupo grupo = getGrupo(idGrupo);
		return grupo.getAtributoEntradaGrupo(idEntrada, atributo);
	}

	/**
	 * Exclui uma entrada de todos os grupos que esta entrada participa.
	 * 
	 * @param idEntrada
	 * @throws SistemaException
	 */
	public void excluirEntradaGrupos(Entrada entrada) throws SistemaException {

		// Metodo que pega uma string com todos os grupos que uma entrada
		// pertence.
		String conjuntoGrupos = entrada.getGruposQueParticipa();
		conjuntoGrupos = conjuntoGrupos.replace("[", "").replace("]", "")
				.replace(",", "");
		StringTokenizer st = new StringTokenizer(conjuntoGrupos);

		// Laco que exclui a entrada de todos os grupos que ela pertence, um
		// grupo por vez.
		while (st.hasMoreTokens()) {
			String idGrupo = st.nextToken();
			excluirEntrada(idGrupo, entrada);
		}

	}

	/**
	 * Exclui uma entrada de um unico grupo.
	 * 
	 * @param idGrupo
	 *            Identificacao do grupo
	 * @param entrada
	 *            Entrada a ser excluida
	 * @throws SistemaException
	 */
	private void excluirEntrada(String idGrupo, Entrada entrada)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		grupo.excluirEntrada(entrada);

	}

	/**
	 * Faz um convite de compartilhamento de grupo a um usuario.
	 * 
	 * 
	 * @param usuarioConvidado Usuario que se deseja convidar;
	 * @param idGrupo Identificacao do grupo.
	 * @throws SistemaException
	 */
	public void fazerConvite(Usuario usuarioConvidado, String idGrupo)
			throws SistemaException {

		usuarioConvidado.receberConvite(idGrupo);
	}

	/**
	 * Adiciona um usuario a um grupo.
	 * 
	 * @param idGrupo Identificacao do grupo.
	 * @param email Email do usuario.
	 * @throws SistemaException
	 */
	public void addUsuarioGrupo(String idGrupo, String email)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		grupo.addMembro(email);

	}

	/**
	 * Altera uma entrada do grupo, se o usuario tiver permissao para isso.
	 * 
	 * 
	 * @param emailUsuario Email do usuario que quer alterar a entrada.
	 * @param idGrupo Identificacao do grupo que contem essa entrada.
	 * @param idEntrada Identificacao da entrada.
	 * @param atributo Atributo que se deseja alterar
	 * @param valor Valor que o atributo assumira.
	 * @throws SistemaException
	 */
	public void alteraEntrada(String emailUsuario, String idGrupo,
			String idEntrada, String atributo, String valor)
			throws SistemaException {

		Grupo grupo = getGrupo(idGrupo);
		if (grupo.ehMembro(emailUsuario)
				&& (grupo.getPermissao().equals("editavel"))) {
			grupo.alteraEntrada(idEntrada,atributo,valor);

		}else{
			throw new SistemaException("Sua permissao eh apenas para leitura.");
		}

	}

	/**
	 * Remove um usuario do grupo.
	 * 
	 * 
	 * @param idGrupo Identificacao do grupo.
	 * @param email Email a ser removido do grupo.
	 * @throws SistemaException
	 */
	public void removeUsuarioGrupo(String idGrupo, String email) throws SistemaException {
		
		Grupo grupo = getGrupo(idGrupo);
		grupo.removeMembro(email);
		
	}

	public void excluirGrupo(String idGrupo, String email) throws SistemaException {
		
		Grupo grupo = getGrupo(idGrupo);
		if(grupo.getDonoGrupo().equals(email)){
			grupo.removeEntradas();
			mapeadorGrupos.remove(idGrupo);
		} else{
			throw new SistemaException("Voce nao tem permissao para excluir esse grupo.");
		}
		
		
		
	}

}
